package filters

import (
	"encoding/json"
	"strconv"

	"boomlive.com/boomlive-common/configs"
	"boomlive.com/boomlive-common/constants"
	"boomlive.com/boomlive-common/utils"
	"github.com/beego/beego/v2/core/logs"
	beecontext "github.com/beego/beego/v2/server/web/context"
)

func FilterToken(ctx *beecontext.Context) {
	isOpen := configs.FilterTokenIsOpen

	if isOpen == 0 {
		return
	}

	sourceType := ctx.Input.Header("Source-Type")
	if sourceType == "develop" {
		// 临时测试用 todo 后续删除
		return
	}

	body := string(ctx.Input.RequestBody)

	if body == "" {
		return
	}

	token := ctx.Request.Header.Get("Api-Token")

	if token == "" {
		logs.Warn("token is empty requestId=%s", ctx.Input.GetData("requestId"))
		tokenValidateFail(ctx)
		return
	}

	type uidStruct struct {
		UserId string `json:"user_id"`
	}

	var uidJson uidStruct

	err := json.Unmarshal([]byte(body), &uidJson)

	if err != nil {
		logs.Warn("json.Unmarshal error: %v body=%s requestId=%s", err, body, ctx.Input.GetData("requestId"))
		tokenValidateFail(ctx)
		return
	}

	var userId int64
	userId, err = strconv.ParseInt(uidJson.UserId, 10, 64)

	if err != nil {
		logs.Warn("strconv.ParseInt error: %v body=%s requestId=%s", err, body, ctx.Input.GetData("requestId"))
		tokenValidateFail(ctx)
		return
	}

	realToken := GetUserToken(userId, ctx)

	if realToken == "" {
		logs.Warn("redis token is empty requestId=%s", ctx.Input.GetData("requestId"))
		tokenValidateFail(ctx)
		return
	}

	if token != realToken {
		logs.Warn("token is invalid requestId=%s", ctx.Input.GetData("requestId"))
		tokenValidateFail(ctx)
		return
	}
}

func GetUserToken(userId int64, ctx *beecontext.Context) string {

	cacheKey := configs.FilterTokenCacheKey

	if cacheKey == "" {
		logs.Error("filterToken::cacheKey is empty requestId=%s", ctx.Input.GetData("requestId"))
		return ""
	}

	redis := utils.RedisService{}

	token := redis.HGet(cacheKey, strconv.FormatInt(userId, 10))

	return token
}

func tokenValidateFail(ctx *beecontext.Context) {
	res := utils.GenerateResultBody(constants.ERR_USER_NOT_AUTH, nil, utils.GetLanguageCode(ctx))
	_ = ctx.Output.JSON(res, false, false)
}
